Skip to content

Conversation

@surbhiia
Copy link

@surbhiia surbhiia commented Dec 16, 2025

As discussed in the Add HTTP span events for network phases breakdown issue in semantic-convention repo, this PR resolves this issue in this repo.

Changes made in this PR:

  • Upgrade Okhttp library version from 3.0.0 to 3.11 as OkHttp EventListener was introduced in 3.11.
  • Adds an internal NetworkTimingEventListener factory that captures the network phases breakdown timing as attributes in the current span.
  • A new API was added that allows customers to get an okhttp3 call factory with this event listener attached (OkHttpTelemetry.newCallFactoryWithNetworkTiming) , the existing API and functionality remains unaffected.
  • Add a test for same in available tests in the library.
  • Some other minor changes needed after upgrade to 3.11.

@surbhiia surbhiia requested a review from a team as a code owner December 16, 2025 12:28

dependencies {
library("com.squareup.okhttp3:okhttp:3.0.0")
library("com.squareup.okhttp3:okhttp:3.11.0")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of a tangent to this PR, but I'd be surprised if folks are still using versions this old given it was released back in 2018, and would imagine most folks are using either 4 or 5.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we create an issue to discuss and evaluate this and address it as needed in a separate PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we create an issue to discuss and evaluate this and address it as needed in a separate PR?

In my opinion creating an issue won't help as this PR won't be merged before there is a decision on whether to increase the minimum supported version or not. Generally we are open to bumping the minimum supported version for library instrumetnations, but prefer to keep supporting old versions in the agent instrumentation. Here I suspect that bumping the version isn't really required since the instrumentation actually works with the old version, only the new network listener doesn't. You could avoid the discussion by replacing library("com.squareup.okhttp3:okhttp:3.0.0") with compileOnly("com.squareup.okhttp3:okhttp:3.11.0") and testLibrary("com.squareup.okhttp3:okhttp:3.0.0") and placing the network listener test into separate suite that tests with 3.11.0.


@Override
public void callStart(Call call) {
Span.current().setAttribute(CALL_START, System.currentTimeMillis());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might not work when the event happens on a background thread. Are you sure that all of these callbacks are invoked so that the can see the current http client span?


@Override
public void dnsStart(Call call, String domainName) {
Span.current().setAttribute(DNS_START, System.currentTimeMillis());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The span start/end timestamps use nanoseconds, perhaps to be consistent with that and to be able to measure sub millisecond operations it would also make sense to use nanos here?
Also to accurately measure durations start and end time would need to be captured from a monotonic source.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually the span event itself already includes the event creation timestamp in nanoseconds so perhaps adding another timestamp isn't needed at all

return "http";
case SPDY_3:
return "spdy";
default:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was required as build was failing with error prone issue - Missing cases in enum switch
Errorprone issue

}

@Override
public Call clone() throws CloneNotSupportedException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are these changes needed?

Copy link
Author

@surbhiia surbhiia Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In okhttp 3.11, CloneNotSupportedException is not thrown from the method, we still need to have the try catch block because super.clone can throw the exception.

okhttp3.Request request =
new okhttp3.Request.Builder().url(resolveAddress("/success").toString()).build();
okhttp3.Response response =
createCallFactoryWithNetworkTiming(new OkHttpClient.Builder()).newCall(request).execute();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should also test enqueue to verify that you get the expected events when request is running in a background thread.

attrs.asMap().keySet().stream()
.map(AttributeKey::getKey)
.anyMatch(
k -> k.endsWith(".start_time") || k.endsWith(".end_time"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't really verify much. I think you should assert all the events that you expect. This would also let you verify whether there are some events that are not recorded on the span.

@surbhiia surbhiia marked this pull request as draft December 17, 2025 15:21

@Override
public void dnsStart(Call call, String domainName) {
Span.current().setAttribute(DNS_START, System.currentTimeMillis());
Copy link

@atulgpt atulgpt Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will using Span.current() always ensure that this event is being added to the okhttp call tracing span?
It can happen that before this method call and after the okhttp trace span start some other span got started

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OkHttp3 library enhancement for gathering network phases timing via HTTP Span Events

4 participants